#include "VSOneParamAnimBlend.h"
#include "VSGraphicInclude.h"
#include "VSStream.h"
using namespace VSEngine2;
IMPLEMENT_RTTI(VSOneParamAnimBlend,VSAnimBlendFunction)
static bool gs_bStreamRegistered_VSOneParamAnimBlend= VSOneParamAnimBlend::RegisterMainFactory();
bool VSOneParamAnimBlend::ms_bRegisterMainFactory = false;
bool VSOneParamAnimBlend::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSOneParamAnimBlend::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSOneParamAnimBlend::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);

	return 1;
}
VSObject * VSOneParamAnimBlend::FactoryFunc()
{
	return VS_NEW VSOneParamAnimBlend;

}
unsigned int VSOneParamAnimBlend::DiskUse()const
{
	unsigned int Used = VSAnimBlendFunction::DiskUse();

	Used += sizeof(VSREAL) * 2;


	return Used;
}
bool VSOneParamAnimBlend::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSAnimBlendFunction::Save(rStream,iSaveUse))
		return 0;

	

	if(!rStream.Write(&m_fParamMax,sizeof(VSREAL)))
		return 0;
	iSaveUse += sizeof(VSREAL);

	if(!rStream.Write(&m_fParamMin,sizeof(VSREAL)))
		return 0;
	iSaveUse += sizeof(VSREAL);


	return 1;
}
bool VSOneParamAnimBlend::Load(VSStream & rStream,unsigned int &iSaveUse)
{	
	if(!VSAnimBlendFunction::Load(rStream,iSaveUse))
		return 0;


	if(!rStream.Read(&m_fParamMax,sizeof(VSREAL)))
		return 0;
	iSaveUse += sizeof(VSREAL);

	if(!rStream.Read(&m_fParamMin,sizeof(VSREAL)))
		return 0;
	iSaveUse += sizeof(VSREAL);



	return 1;
}

bool VSOneParamAnimBlend::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSOneParamAnimBlend* Temp = DynamicCast<VSOneParamAnimBlend>(pObject); 
	if(!Temp)
		return 0;
	if(VSAnimBlendFunction::Clone(pObject,uiType))
	{

		m_fParamMax = Temp->m_fParamMax;
		m_fParamMin = Temp->m_fParamMin;
		return 1;

	}
	else
	{
		return 0;
	}

}
VSOneParamAnimBlend::~VSOneParamAnimBlend()
{

}
VSOneParamAnimBlend::VSOneParamAnimBlend()
{
	m_fParam = 0.0f;
	m_fParamMax = 1.0f;
	m_fParamMin = -1.0f;
}
VSOneParamAnimBlend::VSOneParamAnimBlend(const VSUsedName & ShowName,VSAnimTree * pAnimTree)
				:VSAnimBlendFunction(ShowName,pAnimTree)
{
	m_fParam = 0.0f;
	m_fParamMax = 1.0f;
	m_fParamMin = -1.0f;

	
	VSString InputName0 = _T("Child0");
	VSInputNode * pInputNode = NULL;
	pInputNode = VS_NEW VSInputNode(VSPutNode::AVT_ANIM,InputName0,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);
	m_NodeCrossFadingTime.AddElement(0.0f);

	VSString InputName1 = _T("Child1");
	pInputNode = NULL;
	pInputNode = VS_NEW VSInputNode(VSPutNode::AVT_ANIM,InputName1,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);
	m_NodeCrossFadingTime.AddElement(0.0f);
}
void VSOneParamAnimBlend::AddInputNode()
{
	VSString InputName = _T("Child");
	VSString ID = IntToString(m_pInput.GetNum()); 
	InputName += ID;
	VSInputNode * pInputNode = NULL;
	pInputNode = VS_NEW VSInputNode(VSPutNode::AVT_ANIM,InputName,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);
	m_NodeCrossFadingTime.AddElement(0.0f);
}
void VSOneParamAnimBlend::DeleteInputNode()
{
	if (m_pInput.GetNum() > 2)
	{
		VSInputNode * pInputNode = m_pInput[m_pInput.GetNum() - 1];

		m_pInput.Erase(m_pInput.GetNum() - 1);
		if (!pInputNode)
		{
			return ;
		}
		VSMAC_DELETE(pInputNode);
		m_NodeCrossFadingTime.Erase(m_NodeCrossFadingTime.GetNum() - 1);
	}
}
bool VSOneParamAnimBlend::ComputePara(double dAppTime)
{
	if (m_fParam < m_fParamMin)
	{
		m_fParam = m_fParamMin;
	}
	else if (m_fParam > m_fParamMax)
	{
		m_fParam = m_fParamMax;
	}
	return 1;
}
bool VSOneParamAnimBlend::ComputeOutBoneMatrix(double dAppTime)
{
	VSREAL fInternal = m_fParamMax - m_fParamMin;
	VSREAL fInternalSeg = fInternal / (m_pInput.GetNum() - 1);
	if (fInternalSeg < EPSILON_E4)
	{
		return 0;
	}
	unsigned int uiIndex1 = 0;
	unsigned int uiIndex2 = 0;

	float fTemp = (m_fParam - m_fParamMin) / fInternalSeg;
	uiIndex1 = (unsigned int)fTemp;
	
	if (uiIndex1 >= m_pInput.GetNum() - 1)
	{
		uiIndex2 = uiIndex1;
	}
	else
	{
		uiIndex2 = uiIndex1 + 1;
	}
	
	if (m_uiCrossFadingType == CFT_SMOOTH)
	{
		VSREAL fWeight = fTemp - (float)uiIndex1;


		VSInputNode* pInputNode1 = GetInputNode(uiIndex1);
		VSInputNode* pInputNode2 = GetInputNode(uiIndex2);
		if(pInputNode1->GetOutputLink() && pInputNode2->GetOutputLink())
		{
			VSAnimFunction *pAnimBaseFunction1 = (VSAnimFunction *)pInputNode1->GetOutputLink()->GetOwner();
			VSAnimFunction *pAnimBaseFunction2 = (VSAnimFunction *)pInputNode2->GetOutputLink()->GetOwner();
			LineBlendTwo(this,pAnimBaseFunction1,pAnimBaseFunction2,fWeight);
		}
	}
	else if (m_uiCrossFadingType == CFT_IMMEDIATE)
	{
		if (m_uiLastAnimIndex == VSMAX_INTEGER)
		{
			m_uiLastAnimIndex = uiIndex1;		
		}
		
		if (m_uiLastAnimIndex != uiIndex1)
		{
			if (m_fCrossFadingTime < m_NodeCrossFadingTime[uiIndex1])
			{
				VSREAL fWeight = 0.0f;
// 				if (m_NodeCrossFadingTime[uiIndex1] > EPSILON_E4)
// 				{
				fWeight = m_fCrossFadingTime / m_NodeCrossFadingTime[uiIndex1];
/*				}*/
				
				VSInputNode* pInputNode1 = GetInputNode(m_uiLastAnimIndex);
				VSInputNode* pInputNode2 = GetInputNode(uiIndex1);
				if(pInputNode1->GetOutputLink() && pInputNode2->GetOutputLink())
				{
					VSAnimFunction *pAnimBaseFunction1 = (VSAnimFunction *)pInputNode1->GetOutputLink()->GetOwner();
					VSAnimFunction *pAnimBaseFunction2 = (VSAnimFunction *)pInputNode2->GetOutputLink()->GetOwner();
					LineBlendTwo(this,pAnimBaseFunction1,pAnimBaseFunction2,fWeight);
				}
				m_fCrossFadingTime += (VSREAL)m_dIntervalTime;
			}
			else 
			{
				m_uiLastAnimIndex = uiIndex1;
				m_fCrossFadingTime = 0.0f;
				VSInputNode* pInputNode1 = GetInputNode(uiIndex1);
				if(pInputNode1->GetOutputLink())
				{
					VSAnimFunction *pAnimBaseFunction1 = (VSAnimFunction *)pInputNode1->GetOutputLink()->GetOwner();
					LineBlendTwo(this,pAnimBaseFunction1,NULL,0.0f);
				}
			}
		}
		else
		{
			VSInputNode* pInputNode1 = GetInputNode(uiIndex1);
			if(pInputNode1->GetOutputLink())
			{
				VSAnimFunction *pAnimBaseFunction1 = (VSAnimFunction *)pInputNode1->GetOutputLink()->GetOwner();
				LineBlendTwo(this,pAnimBaseFunction1,NULL,0.0f);
			}
		
		}
			
			
		
	}
	
	return 1;
}